Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inject balances from json into chainspec #3114

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

dariolina
Copy link
Member

It is required to keep the chain spec file manageable with thousands of balances. The JSON file is NOT final as it only contains farmer rewards and no other allocations (team, fdn, etc.).
Tested on devnet on Oct 9.

Code contributor checklist:

Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure we need to include this in the software in JSON? It'll make every node build ~12M larger. Compressing it with zstd will reduce the size to ~4M for example.

use sp_runtime::traits::Zero;

pub fn get_genesis_allocations() -> Vec<(AccountId, Balance)> {
let file_content = include_str!("genesis_allocations.json");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We typically store such things in a constant at the top of the file, not in local variable, see the chain spec example. Also I'd make this function take contents as an argument with constant that contains JSON being in the chain spec file.

let allocations: Value = serde_json::from_str(file_content)
.expect("Failed to parse genesis allocations JSON");

allocations.as_array()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these types implement Serde. You can just define the shape and then decode the whole thing without manually iterating over it, for balances you can use NonZeroU128 to automatically check the invariant.

That is unless you want to have nice error messages here (that should never really happen anyway).

Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure we need to include this in the software in JSON? It'll make every node build ~12M larger. Compressing it with zstd will reduce the size to ~4M for example.

Can we reduce the file size using arrays rather than key/value maps?
That would look like:

[
  [
    "stBJ4naCdaku9nTXrcQ8m8XQSa4arro9pSdW3eaj6skgW9Nwg",
    "1000000000000000000000"
  ],
  [
    "st9idRv3z62dVwfmjLaNiq1FVb2B2j3giib7ns4Vni1wZ9ePj",
    "1106022470000000000000000"
  ],
  ...
]

It also seems like all the amounts end in 15 zeroes, so maybe we could do that multiplication in code?

If this large file isn't final, then compressing it will also add 4 MB to the Git repository every time it changes. If we are going to compress it, there's no need for so much white space, so we could run it through a script that removes all white space before compressing it.

If it's uncompressed, it will add 12 MB to Git, but the diffs will be smaller.

Is there a way to just store the file hash in the node/git, and download the latest file when the node starts? Or distribute the file with the node build?

@nazar-pc
Copy link
Member

Is there a way to just store the file hash in the node/git, and download the latest file when the node starts? Or distribute the file with the node build?

This is supposed to be a part of the chain spec, so it will be awkward to distribute it separately and I'd really prefer to not have it depend on the download from somewhere.

At the same time this large blob will end up copied into the actual mainnet chain spec, which in turn means our chain spec will be permanently huge. So we will remove the file shortly afterwards, but the ballooned chain spec will stay with us basically forever.

Repo size is a smaller concern for me, this is a really important information to have persisted in history. But I agree that we should wait for the very final version rather than adding multiple revisions of this large file.

@dariolina
Copy link
Member Author

I have added the file, even if not final, to test the "real deal" and wanted us to align on a preferred way to handle such case, because that is the size of the file we will be dealing with on mainnet. If we decide on format/workflow here, in the next PR I can just swap the allocations file for the final one.
There is no way to avoid ballooned mainnet chainspec, however, these are not strictly necessary for testnet, so we could save some there.

@NingLin-P
Copy link
Member

Perhaps adding the file to a separate repro and using it as git submodule can help to reduce the mono repo size.

@nazar-pc
Copy link
Member

Perhaps adding the file to a separate repro and using it as git submodule can help to reduce the mono repo size.

It really doesn't if you need to clone submodule for code to compile anyway 🙂

@dariolina
Copy link
Member Author

dariolina commented Oct 11, 2024

It also seems like all the amounts end in 15 zeroes, so maybe we could do that multiplication in code?

In the final file it will be closer to 8 trailing zeroes, but I would rather not introduce into the code assumptions about precision of underlying file.

@teor2345
Copy link
Contributor

There is no way to avoid ballooned mainnet chainspec, however, these are not strictly necessary for testnet, so we could save some there.

I think changing to arrays and removing spaces will help keep the size of the file down. (I don’t want to remove new lines, because that makes diffs much harder to see.)

Is there anything we need to test on testnet that would be missed by having a small chain spec file?
It’s usually better to keep them as similar as possible, unless we’re testing mainnet the same as testnet before every release. (I’ve run into mainnet-only bugs in other distributed networks before.)

@@ -86,7 +87,7 @@ pub fn gemini_3h_compiled() -> Result<GenericChainSpec, String> {
AccountId::from_ss58check("5DNwQTHfARgKoa2NdiUM51ZUow7ve5xG9S2yYdSbVQcnYxBA")
.expect("Wrong root account address");

let balances = vec![(sudo_account.clone(), 1_000 * SSC)];
let balances=get_genesis_allocations(GENESIS_ALLOCATIONS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should make rustfmt happier

Suggested change
let balances=get_genesis_allocations(GENESIS_ALLOCATIONS);
let balances = get_genesis_allocations(GENESIS_ALLOCATIONS);

@dariolina
Copy link
Member Author

(I don’t want to remove new lines, because that makes diffs much harder to see.)

In the next iteration, the file will change basically on every line since the precision will be higher and post-merge there should not ever be a diff to genesis balances.

@teor2345
Copy link
Contributor

(I don’t want to remove new lines, because that makes diffs much harder to see.)

In the next iteration, the file will change basically on every line since the precision will be higher and post-merge there should not ever be a diff to genesis balances.

Sure, we can always run it through jq to format and then do a diff. So whatever you want to do to minify is fine with me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants